/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.github.florent37.camerafragment.internal.utils;

import ohos.agp.components.Image;
import ohos.agp.utils.Matrix;
import ohos.agp.utils.Point;
import ohos.agp.window.service.Display;
import ohos.agp.window.service.DisplayManager;
import ohos.app.Context;
import ohos.media.image.ImageSource;
import ohos.media.image.PixelMap;
import ohos.media.image.common.PixelFormat;

import java.util.Optional;

/**
 * 图片下载
 *
 * @since 2021-05-25
 */
public class ImageLoader {
    /**
     * 正常方向
     */
    public static final int ORIENTATION_NORMAL = 1;
    /**
     * 定向水平翻转
     */
    public static final int ORIENTATION_FLIP_HORIZONTAL = 2;
    /**
     * 方向垂直翻转
     */
    public static final int ORIENTATION_FLIP_VERTICAL = 4;
    /**
     * 方向旋转90
     */
    public static final int ORIENTATION_ROTATE_90 = 6;
    /**
     * 方向旋转180
     */
    public static final int ORIENTATION_ROTATE_180 = 3;
    /**
     * 方向旋转270
     */
    public static final int ORIENTATION_ROTATE_270 = 8;
    /**
     * 方向转置
     */
    public static final int ORIENTATION_TRANSPOSE = 5;
    /**
     * 方向横向
     */
    public static final int ORIENTATION_TRANSVERSE = 7;

    private static final double CONSTANT_0_8 = 0.8;
    private static final int NEGATIVE = -1;
    private static final int ROTATE_90 = 90;
    private static final int ROTATE_180 = 180;

    private Context context;
    private String url;

    private ImageLoader(Context context) {
        this.context = context;
    }

    /**
     * Builder
     *
     * @since 2021-05-25
     */
    public static class Builder {
        private ImageLoader imageLoader;

        /**
         * 构造函数
         *
         * @param context 上下文
         */
        public Builder(Context context) {
            imageLoader = new ImageLoader(context);
        }

        /**
         * 加载
         *
         * @param url 图片地址
         * @return Builder
         */
        public Builder load(String url) {
            imageLoader.url = url;
            return this;
        }

        /**
         * build 创建
         *
         * @return ImageLoader
         */
        public ImageLoader build() {
            return imageLoader;
        }
    }

    /**
     * 加载到Image
     *
     * @param target Image控件
     */
    public void into(final Image target) {
        PixelMap decodedBitmap = decodeSampledBitmapFromResource();
        PixelMap resultBitmap = rotateBitmap(decodedBitmap, getExifOrientation());
        target.setPixelMap(resultBitmap);
    }

    private PixelMap decodeSampledBitmapFromResource() {
        Optional<Display> defaultDisplay = DisplayManager.getInstance().getDefaultDisplay(context);
        Point pt = new Point();
        defaultDisplay.get().getSize(pt);
        ImageSource imageSource = ImageSource.create(url, new ImageSource.SourceOptions());
        ImageSource.DecodingOptions options = new ImageSource.DecodingOptions();
        options.editable = false;
        options.desiredSize = imageSource.getImageInfo().size;
        int width = defaultDisplay.get().getAttributes().width;
        int height = defaultDisplay.get().getAttributes().height;
        options.desiredSize.width = width;
        options.desiredSize.height = (int) (height * CONSTANT_0_8);
        options.desiredPixelFormat = PixelFormat.ARGB_8888;
        return imageSource.createPixelmap(options);
    }

    // 图片裁剪
    private PixelMap rotateBitmap(PixelMap bitmap, int orientation) {
        Matrix matrix = new Matrix();
        switch (orientation) {
            case ORIENTATION_FLIP_HORIZONTAL:
                matrix.setScale(NEGATIVE, 1);
                break;
            case ORIENTATION_ROTATE_180:
                matrix.setRotate(ROTATE_180);
                break;
            case ORIENTATION_FLIP_VERTICAL:
                matrix.setRotate(ROTATE_180);
                matrix.postScale(NEGATIVE, 1);
                break;
            case ORIENTATION_TRANSPOSE:
                matrix.setRotate(ROTATE_90);
                matrix.postScale(NEGATIVE, 1);
                break;
            case ORIENTATION_ROTATE_90:
                matrix.setRotate(ROTATE_90);
                break;
            case ORIENTATION_TRANSVERSE:
                matrix.setRotate(-ROTATE_90);
                matrix.postScale(NEGATIVE, 1);
                break;
            case ORIENTATION_ROTATE_270:
                matrix.setRotate(-ROTATE_90);
                break;
            case ORIENTATION_NORMAL:
            default:
                return bitmap;
        }

        try {
            PixelMap.InitializationOptions options = new PixelMap.InitializationOptions();
            options.size = bitmap.getImageInfo().size;
            options.size.width = bitmap.getImageInfo().size.width;
            options.size.height = bitmap.getImageInfo().size.height;
            PixelMap bmRotated = PixelMap.create(bitmap, options);
            bitmap.release();
            return bmRotated;
        } catch (OutOfMemoryError ignore) {
            Log.error("JACK", "rotateBitmap OutOfMemoryError ignore :" + ignore.getLocalizedMessage());
            PixelMap.InitializationOptions options = new PixelMap.InitializationOptions();
            return PixelMap.create(bitmap, options);
        }
    }

    private int getExifOrientation() {
        return ORIENTATION_NORMAL;
    }
}
